package cn.myzqu.sign.common.excel.export;

import cn.myzqu.sign.common.excel.annotations.Excel;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * describe:
 *
 * @author 的川
 * @date 2019/02/27
 */
public class ExportExcel<T> {

    /**
     * 声明工作薄
     */
    private Workbook workbook;

    /**
     * 表头行样式
     */
    private CellStyle headerStyle;

    /**
     * 数据行样式
     */
    private CellStyle cellStyle;


    public ExportExcel() {
        workbook = new XSSFWorkbook();
        //初始化表头样式
        initTitleStyle(workbook);
        //初始化内容样式
        initContentStyle(workbook);
    }

    public void exportExcel(String title , Collection<T> dataSet, OutputStream out) throws Exception{
        exportExcel( title , dataSet, out, "yyyy-MM-dd HH:mm:ss");
    }


    private void exportExcel( String title ,Collection<T> dataSet, OutputStream out, String pattern) throws Exception{
        //1.设置表格
        Sheet sheet = workbook.createSheet(title);
        //设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth(20);
        //2.设置表头行
        getHeader(sheet , dataSet);
        //3.遍历集合数据，产生数据行
        Iterator<T> it = dataSet.iterator();
        int index = 0;
        Row row;
        Cell cell;
        while (it.hasNext()) {
            index++;
            row = sheet.createRow(index);
            T t = (T) it.next();
            // 利用反射，根据JavaBean属性的先后顺序，动态调用getXxx()方法得到属性值
            Field[] fields  = t.getClass().getDeclaredFields();
            int i = 0;
            for (Field field : fields) {
                //判断是否有Excel注解
                if(field.isAnnotationPresent(Excel.class)){
                    cell = row.createCell(i++);
                    cell.setCellStyle(cellStyle);
                    String fieldName = field.getName();
                    String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase()
                            + fieldName.substring(1);
                    Class tCls = t.getClass();
                    Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
                    Object value = getMethod.invoke(t, new Object[] {});
                    // 判断值的类型后进行强制类型转换
                    typeCast(value , cell , pattern);
                }
            }
        }
        //写入数据
        workbook.write(out);
    }

    /**
     * 设置表头行
     * @param sheet
     * @param dataSet
     */
    private void getHeader(Sheet sheet , Collection<T> dataSet){
        Iterator<T> it = dataSet.iterator();
        Object object  =  it.next();
        getHeader(sheet , object);

    }


    /**
     * 设置表头行
     * @param sheet
     * @param t
     */
    private void getHeader(Sheet sheet, Object t){
        Row row = sheet.createRow(0);
        Cell cellHeader;
        Field[] fields  = t.getClass().getDeclaredFields();
        int i = 0;
        for(Field field : fields){
            if(field.isAnnotationPresent(Excel.class)){
                //获取注解上的headerName值
                Excel excel = field.getAnnotation(Excel.class);
                String headerName = excel.headerName();
                cellHeader = row.createCell(i++);
                cellHeader.setCellStyle(headerStyle);
                cellHeader.setCellValue(new XSSFRichTextString(headerName));
            }
        }
    }

    /**
     * 初始化标题样式
     * @param workbook
     */
    private void initTitleStyle(Workbook workbook){
        headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(HSSFColor.BLUE_GREY.index);
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        headerStyle.setBorderBottom(BorderStyle.THIN);
        headerStyle.setBorderLeft(BorderStyle.THIN);
        headerStyle.setBorderRight(BorderStyle.THIN);
        headerStyle.setBorderTop(BorderStyle.THIN);
        headerStyle.setAlignment(HorizontalAlignment.CENTER);

        //设置标题字体
        Font titleFont = workbook.createFont();
        titleFont.setBold(true);
        titleFont.setFontName("宋体");
        titleFont.setColor(HSSFColor.WHITE.index);
        titleFont.setFontHeightInPoints((short) 11);
        headerStyle.setFont(titleFont);

    }
    /**
     * 初始化内容样式
     * @param workbook
     */
    private void initContentStyle(Workbook workbook){
        cellStyle = workbook.createCellStyle();
        cellStyle.setFillForegroundColor(HSSFColor.WHITE.index);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        //初始化字体样式
        Font font = workbook.createFont();
        font.setBold(false);
        cellStyle.setFont(font);
    }
    /**
     * 类型强制转换
     * @param value
     * @param cell
     * @param datePattern
     */
    private void typeCast(Object value, Cell cell , String datePattern) {
        Pattern p = Pattern.compile("^//d+(//.//d+)?$");
        SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
        Matcher matcher;
        String textValue = null;
        if (value instanceof Integer) {
            cell.setCellValue((Integer) value);
        } else if (value instanceof Float) {
            textValue = String.valueOf(value);
            cell.setCellValue(textValue);
        } else if (value instanceof Double) {
            textValue = String.valueOf(value);
            cell.setCellValue(textValue);
        } else if (value instanceof Long) {
            cell.setCellValue((Long) value);
        }
        if (value instanceof Boolean) {
            textValue = "是";
            if (!(Boolean) value) {
                textValue = "否";
            }
        } else if (value instanceof Date) {
            textValue = sdf.format((Date) value);
        } else {
            // 其它数据类型都当作字符串简单处理
            if (value != null) {
                textValue = value.toString();
            }
        }
        if (textValue != null) {
            matcher = p.matcher(textValue);
            if (matcher.matches()) {
                // 是数字当作double处理
                cell.setCellValue(Double.parseDouble(textValue));
            } else if ( cell instanceof XSSFCell) {
                XSSFRichTextString richString = new XSSFRichTextString(textValue);
                cell.setCellValue(richString);
            } else if ( cell instanceof HSSFCell){
                HSSFRichTextString richString = new HSSFRichTextString(textValue);
                cell.setCellValue(richString);
            }
        }
    }
}
